home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / pxewin.zip / DBDISPLY.CPP < prev    next >
Text File  |  1992-02-17  |  17KB  |  664 lines

  1. // PXEWIN - (C) Copyright 1992 by Beam Engineering, INC.
  2.  
  3. // DBDISPLY_CPP //
  4.  
  5. // Contents ----------------------------------------------------------------
  6. //
  7. //    This header contains members for the DBDISPLAY class.
  8. //
  9. // End ---------------------------------------------------------------------
  10.  
  11. // External Reference Name For This Header ---------------------------------
  12.  
  13. #ifndef DBDISPLY_CPP
  14.     #define DBDISPLY_CPP
  15.  
  16. // End ---------------------------------------------------------------------
  17.  
  18. // Interface Dependencies --------------------------------------------------
  19.  
  20. #ifndef DBDISPLY_HPP
  21.     #include "dbdisply.hpp"
  22. #endif // DBDISPLY_HPP //
  23.  
  24. #ifndef PXLISTBX_CPP
  25.     #include "pxlistbx.cpp"
  26. #endif // PXLISTBX_CPP //
  27.  
  28. #ifndef BROWSE_HPP
  29.     #include "browse.hpp"
  30. #endif // BROWSE_HPP //
  31.  
  32. // End ---------------------------------------------------------------------
  33.  
  34. // constructor DBDISPLAY //
  35.  
  36. inline DBDISPLAY::DBDISPLAY()
  37. {
  38.     my_parm = NULL;
  39.     UpdateFlag = 1;
  40.  
  41.     // Set your engine object pointer to this
  42.  
  43.     EngDataPtr->PXEObjPtr = this;
  44.     top_rec = 1;
  45.     item = 0;
  46.     field = 0;
  47. }
  48.  
  49. // Description -------------------------------------------------------------
  50. //
  51. //    Constructor for DBDISPLAY.  Set my_parm to NULL, UpdateFlag for
  52. //    display updates, set the EngDataPtr to this object since it will
  53. //    be the parent object, top_rec to first record, item to first item
  54. //    in the list box.  field is the first field in the record.
  55. //
  56. // End ---------------------------------------------------------------------
  57.  
  58. // member build of DBDISPLAY //
  59.  
  60. PTStreamable DBDISPLAY::build()
  61. {
  62.     return new DBDISPLAY(streamableInit);
  63. }
  64.  
  65. TStreamableClass RegDBDISPLAY("DBDISPLAY",DBDISPLAY::build,
  66.     __DELTA(DBDISPLAY));
  67.  
  68. // Description -------------------------------------------------------------
  69. //
  70. //    When the streamable constructor is called, TStreamable dispatches
  71. //    the build member to construct the object.  To do this, it must
  72. //    know where to find this member functions for the specific class.
  73. //    This is the reason for the stream registration.
  74. //
  75. // End ---------------------------------------------------------------------
  76.  
  77. // member read of DBDISPLAY //
  78.  
  79. inline Pvoid DBDISPLAY::read(Ripstream is)
  80. {
  81.     PXDIS::read(is);
  82.     my_parm = NULL;
  83.     UpdateFlag = 1;
  84.  
  85.     // Set your engine object pointer to this
  86.  
  87.     EngDataPtr->PXEObjPtr = this;
  88.     is >> (RECORDNUMBER)top_rec >> item;
  89.     return this;
  90. }
  91.  
  92. // Summary -----------------------------------------------------------------
  93. //
  94. //    Read this object off the stream.
  95. //
  96. // Parameters
  97. //
  98. //    is.  The incomming stream.
  99. //
  100. // Return Value
  101. //
  102. //    Returns this objects pointer.
  103. //
  104. // Functional Description
  105. //
  106. //      1.  Call base class reader.
  107. //    2.  Intialize as you would in the constructor.
  108. //    3.  Get the top_rec and item off the stream.
  109. //
  110. // End ---------------------------------------------------------------------
  111.  
  112. // member write of DBDISPLAY //
  113.  
  114. inline void DBDISPLAY::write(Ropstream os)
  115. {
  116.     PXDIS::write(os);
  117.     os << (RECORDNUMBER)top_rec << item;
  118. }
  119.  
  120. // Summary -----------------------------------------------------------------
  121. //
  122. //    Write top_rec and item to the stream.
  123. //
  124. // End ---------------------------------------------------------------------
  125.  
  126. // member FillBoxes //
  127.  
  128. void DBDISPLAY::FillBoxes(RECORDNUMBER rec)
  129. {
  130.     int i;                    /* Field index */
  131.     int j;                    /* Record index */
  132.     int sel;                /* Temperary item selection
  133.                            variable */
  134.     int upper_limit;            /* Number of records to
  135.                            get */
  136.     Pchar temp;
  137.  
  138.     // Set mouse cursor to wait
  139.  
  140.     SendMessage(AP->Parent->HWindow,WM_SETWTCUR,0,0);
  141.  
  142.     // Reset update flag
  143.  
  144.     UpdateFlag = 0;
  145.  
  146.     // Check and see if record number is less than first record.
  147.  
  148.     if(rec < 1)
  149.         rec = 1;
  150.  
  151.     // Get the number of records in the table.
  152.  
  153.     my_table->NumRecs();
  154.  
  155.     // If you have less records then a PAGE_SIZE, then set your first
  156.     // record of the page to the first record in the database.  Set the
  157.     // upper limit of the last record you will get to the number of
  158.     // records in the database.
  159.  
  160.     if(EngDataPtr->num_recs < PAGE_SIZE)
  161.     {
  162.         upper_limit = EngDataPtr->num_recs;
  163.         top_rec = 1;
  164.     }
  165.     else
  166.     {
  167.  
  168.         // Else, set the upper limit to the page size.
  169.  
  170.         upper_limit = PAGE_SIZE;
  171.  
  172.         // If you are less than a page size away from the end of the
  173.         // database, set the top record to the number of records in
  174.         // the database minus the size of the page.
  175.  
  176.         if(rec + PAGE_SIZE > EngDataPtr->num_recs){
  177.             top_rec = EngDataPtr->num_recs - PAGE_SIZE + 1;
  178.             sel = rec - top_rec;
  179.         }
  180.         else
  181.         {
  182.  
  183.             // Else, leave the top record value at the parameter
  184.             // setting.
  185.  
  186.             top_rec = rec;
  187.             sel = item;
  188.         }
  189.     }
  190.  
  191.     // Empty the list boxes.
  192.  
  193.     for(i = 0;i < EngDataPtr->num_fields;i++)
  194.         my_parm[i]->my_box->ClearList();
  195.  
  196.     my_record->GoTo(top_rec);
  197.     for(j = 0;j < upper_limit;j++)
  198.     {
  199.  
  200.         // Get the record data into the record transfer buffer.
  201.  
  202.         my_record->Get();
  203.         for(i = 0;i < EngDataPtr->num_fields;i++)
  204.         {
  205.  
  206.             // Get the field data and put in into the list box.
  207.  
  208.             temp = PXDIS::Get(i);
  209.             my_parm[i]->my_box->AddString(temp);
  210.         }
  211.  
  212.         // Go to the next record.
  213.  
  214.         my_record->RecNext();
  215.     }
  216.  
  217.     // Set item out of bounds so it will pass through range check ok
  218.  
  219.     item = -1;
  220.  
  221.     // Set update flag
  222.  
  223.     UpdateFlag = 1;
  224.  
  225.     // Select the item
  226.  
  227.     SelRecord(sel);
  228.  
  229.     // Set mouse cursor to normal
  230.  
  231.     SendMessage(AP->Parent->HWindow,WM_SETNMCUR,0,0);
  232. }
  233.  
  234. // Summary -----------------------------------------------------------------
  235. //
  236. //    This member fills the list boxes with data from the database.
  237. //
  238. // Parameters
  239. //
  240. //    rec.  This is the record number of the top record in the list boxes.
  241. //
  242. // Return Value
  243. //
  244. //    None.
  245. //
  246. // Functional Description
  247. //
  248. //    1.  Set the mouse cursor to the wait cursor.
  249. //
  250. //    2.  Reset the UpdateFlag so updates will not occur until the list
  251. //    boxes are refilled.  This flag will be read by the PXListBox
  252. //    routine to make sure Updates as they would normally when WMPaint is
  253. //    called (TControl version of WMPaint).
  254. //
  255. //    3.  Range check rec.  If it is less than the first record, reset it
  256. //    to the first record.  For a table that is less the a PAGE_SIZE, limit
  257. //    the upperbound accordingly.  Else the upperbound is the PAGE_SIZE.
  258. //      If rec plus PAGE_SIZE is greater than the number of records then set
  259. //    top_rec to PAGE_SIZE less than the number of records and your
  260. //    selection is somewhere in between.  Else leave rec untouched and
  261. //    set you selection to the top record.
  262. //
  263. //    4.  Empty the list boxes.
  264. //
  265. //    5.  Fill the list boxes.
  266. //
  267. //    6.  You need to set the item number out of bounds so the selection
  268. //    routine sees that the selection has changed.
  269. //
  270. //    7.  Set the UpdateFlag to allow updates and call the selection
  271. //    routine.
  272. //
  273. //    8.  Set the mouse cursor to normal.
  274. //
  275. // End ---------------------------------------------------------------------
  276.  
  277. // member SetUp //
  278.  
  279. int DBDISPLAY::SetUp(PBrowser AParent)
  280. {
  281.     Pchar header;                /* Temp location for header
  282.                         */
  283.     int hd_len;                /* Length of header */
  284.     int char_size;                /* Is the number of ASCII
  285.                            characters it takes to
  286.                            represent the field. */
  287.     int i;                    /* Field index */
  288.     HDC hdc;                /* Window device context */
  289.     char szFaceName[LF_FACESIZE];        /* Recieves current fonts
  290.                            name */
  291.     TEXTMETRIC tm;                /* Data structure for font
  292.                            info.  */
  293.  
  294.     EngDataPtr->name = AParent->name;
  295.     AP = AParent;
  296.     sum = 1;
  297.  
  298.     // Get a context handle in the current window.
  299.  
  300.     hdc = GetDC(AParent->HWindow);
  301.  
  302.     // This will get the name of the type face into the face name array
  303.  
  304.     GetTextFace(hdc,sizeof(szFaceName),szFaceName);
  305.  
  306.     // Load the data structure with the font info.
  307.  
  308.     GetTextMetrics(hdc,&tm);
  309.  
  310.     // We will set the character width to the maximum size just to
  311.     // be on the safe side.
  312.  
  313.     char_width = tm.tmMaxCharWidth;
  314.  
  315.     // Release the handle so you don't run out of handles.
  316.  
  317.     ReleaseDC(AParent->HWindow,hdc);
  318.  
  319.     // Setup database
  320.  
  321.     PXDIS::SetUp(0,0,EXISTS,0);
  322.     if(EngDataPtr->Errors.pxerr != PXSUCCESS)
  323.         return EngDataPtr->Errors.pxerr;
  324.  
  325.     // Make an array of field parameter pointers
  326.  
  327.     my_parm = new PLB_PARM [EngDataPtr->num_fields];
  328.  
  329.     for(i = 0;i < EngDataPtr->num_fields;i++){
  330.         my_parm[i] = new LB_PARM;
  331.  
  332.         // Set up a field pointer
  333.  
  334.         my_parm[i]->my_field = my_field[i];
  335.  
  336.         // If parameter set is the first set, initialize x
  337.         // coordinate of the list box independently.
  338.  
  339.         if(i == 0)
  340.             my_parm[i]->x = 2;
  341.         else{
  342.  
  343.             // Else, the list box coordinate depends on
  344.             // where the previous list box ends.
  345.  
  346.             my_parm[i]->x = my_parm[i - 1]->x +
  347.                 my_parm[i - 1]->w + 2;
  348.         }
  349.  
  350.         // Precalc some things we will be using more than once.
  351.  
  352.         header = my_parm[i]->my_field->RetName();
  353.         hd_len = strlen(header);
  354.         char_size = my_parm[i]->my_field->RetCharSize();
  355.  
  356.         // The width of the list box is calculated.  It is
  357.         // the character size of the field times the
  358.         // character width unless the field header is larger.
  359.  
  360.         if(char_size > hd_len){
  361.             my_parm[i]->w = char_size*char_width;
  362.             sum += char_size;
  363.         }
  364.         else{
  365.             my_parm[i]->w = hd_len*char_width;
  366.             sum += hd_len;
  367.         }
  368.  
  369.         // Set up the list box.
  370.  
  371.         my_parm[i]->my_box = new PXListBox(AParent,i,
  372.             my_parm[i]->x,20,my_parm[i]->w,16.5*PAGE_SIZE);
  373.  
  374.         // Set up header for your list boxes
  375.  
  376.         my_parm[i]->my_header = new TStatic(AParent,-1,
  377.             header,my_parm[i]->x,1,200,15,hd_len + 1);
  378.  
  379.     }
  380.     return PXSUCCESS;
  381. }
  382.  
  383. // Summary -----------------------------------------------------------------
  384. //
  385. //    This sets up the database for displaying all the fields.
  386. //
  387. // Parameters
  388. //
  389. //      AParent.  Needs the parent window object to construct the list boxes
  390. //    and the field headers.
  391. //
  392. // Functional Description
  393. //
  394. //    1.  Call the SetUp routine for setting up the database.
  395. //
  396. //    2.  Construct a parameter array for storing list box info.
  397. //
  398. //    3.  Construct a for loop that will initialize all the fields for
  399. //    display.  The information necessary for storing the list box data is
  400. //    saved in the LB_PARM structure.  Placement locations and sizes of
  401. //    each list box are calculated.  Headers for each field are placed
  402. //    at the top of the list box.
  403. //
  404. // End ---------------------------------------------------------------------
  405.  
  406. // Destructor ~DBDISPLAY //
  407.  
  408. DBDISPLAY::~DBDISPLAY()
  409. {
  410.     int i;                    /* Field index */
  411.  
  412.     // if ther is no parameter pointer, then the number of fields is
  413.     // unknown so set to zero.
  414.  
  415.     if(!my_parm)
  416.         EngDataPtr->num_fields = 0;
  417.     for(i = 0;i < EngDataPtr->num_fields;i++)
  418.         delete my_parm[i];
  419.     delete my_parm;
  420. }
  421.  
  422. // End ---------------------------------------------------------------------
  423.  
  424. // Summary -----------------------------------------------------------------
  425. //
  426. //    Kills all buffers used in DBDISPLAY.
  427. //
  428. // End ---------------------------------------------------------------------
  429.  
  430. // member SelRecord //
  431.  
  432. void DBDISPLAY::SelRecord(int ITEM)
  433. {
  434.     int i;                    /* Field index */
  435.  
  436.     // Range check item
  437.  
  438.     if(ITEM >= PAGE_SIZE)
  439.         ITEM = PAGE_SIZE - 1;
  440.     if(ITEM < 0)
  441.         ITEM = 0;
  442.     if(item == ITEM)
  443.     {
  444.         if(item == 0)
  445.             ScrollDwn();
  446.         else{
  447.             if(item == PAGE_SIZE - 1)
  448.                 ScrollUp();
  449.         }
  450.     }
  451.  
  452.     // Select items if you are somewhere within a page or your have
  453.     // incremented past the page but you are not at the last record.
  454.     // For a decrement before the page you don't need to select since
  455.     // you are doing and insert at the first record.
  456.  
  457.     if((item == PAGE_SIZE - 1) || item != ITEM)
  458.     {
  459.         for(i = 0;i < EngDataPtr->num_fields;i++)
  460.         {
  461.             my_parm[i]->my_box->SetSelIndex(ITEM);
  462.         }
  463.     }
  464.     item = ITEM;
  465. }
  466.  
  467. // Summary -----------------------------------------------------------------
  468. //
  469. //      Selects the record cooresponding to the item number in the list boxes
  470. //
  471. // Parameters
  472. //
  473. //    item.  This is the list box item number.
  474. //
  475. // Return Value
  476. //
  477. //    None.
  478. //
  479. // Description
  480. //
  481. //      1.  The item number is range checked.  If the item number is greater
  482. //    then the page size then it is set to the page size.  If the item
  483. //    number is less than the first item number, it is set to the first
  484. //    item.
  485. //
  486. //    2.  If the old item number is equal to the new item number then check
  487. //    for a scroll up or down situation.  It is scroll up if item is the
  488. //    first item, scroll down if item is the last item in the list box.
  489. //
  490. //    3.  If item selected is at the end of the list or somewhere in
  491. //    the middle of the list, then set all the lists to the same item.
  492. //
  493. // End ---------------------------------------------------------------------
  494.  
  495. // member IncRec of DBDISPLAY //
  496.  
  497. void DBDISPLAY::IncRec()
  498. {
  499.     SelRecord(item + 1);
  500. }
  501.  
  502. // Summary -----------------------------------------------------------------
  503. //
  504. //    Increments an item in the list boxes.
  505. //
  506. // End ---------------------------------------------------------------------
  507.  
  508. // member DecRec of DBDISPLAY //
  509.  
  510. void DBDISPLAY::DecRec()
  511. {
  512.     SelRecord(item - 1);
  513. }
  514.  
  515. // Summary -----------------------------------------------------------------
  516. //
  517. //    Decrements an item in the list boxes.
  518. //
  519. // End ---------------------------------------------------------------------
  520.  
  521.  
  522. // member ScrollUp //
  523.  
  524. void DBDISPLAY::ScrollUp()
  525. {
  526.     int i;                    /* Field index */
  527.  
  528.     // Make sure your not already at the last record in the table.
  529.     // Note that we specifically call for the number of records since
  530.     // this may change as we add and delete records from the database.
  531.  
  532.     my_table->NumRecs();
  533.     if(top_rec + PAGE_SIZE <= EngDataPtr->num_recs){
  534.  
  535.         // Go to the new record and get data
  536.  
  537.         my_record->GoTo(top_rec + PAGE_SIZE);
  538.         my_record->Get();
  539.  
  540.         for(i = 0;i < EngDataPtr->num_fields;i++)
  541.         {
  542.             // Delete the first item in the list
  543.  
  544.             my_parm[i]->my_box->DeleteString(0);
  545.  
  546.             // Add the new next item to the list
  547.  
  548.             my_parm[i]->my_box->AddString(PXDIS::Get(i));
  549.         }
  550.         top_rec++;
  551.     }
  552. }
  553.  
  554. // Summary -----------------------------------------------------------------
  555. //
  556. //    This scrolls the display up by one record.
  557. //
  558. // Parameters
  559. //
  560. //    None.
  561. //
  562. // Return Value
  563. //
  564. //    None.
  565. //
  566. // Description
  567. //
  568. //      1.  Do a boundary check and make sure your not at the last record.
  569. //
  570. //    2.  Go to the last record in the list and get the data.
  571. //
  572. //    3.  For all the lists, delete the first item in the list and add the
  573. //      new data to the end of the list.
  574. //
  575. //    4.  Increment the top record pointer.
  576. //
  577. // End ---------------------------------------------------------------------
  578.  
  579. // member ScrollDwn //
  580.  
  581. void DBDISPLAY::ScrollDwn()
  582. {
  583.     int i;                    /* Field index */
  584.  
  585.     // Make sure your not already at the first record in the table
  586.  
  587.     if(top_rec > 1){
  588.  
  589.         // Go to the new record and get data
  590.  
  591.         top_rec--;
  592.         my_record->GoTo(top_rec);
  593.         my_record->Get();
  594.  
  595.         for(i = 0;i < EngDataPtr->num_fields;i++)
  596.         {
  597.             // Delete the last item in the list
  598.  
  599.             my_parm[i]->my_box->DeleteString(PAGE_SIZE - 1);
  600.  
  601.             // Add the new text item to the begining of the list
  602.  
  603.             my_parm[i]->my_box->InsertString(PXDIS::Get(i),0);
  604.         }
  605.     }
  606. }
  607.  
  608. // Summary -----------------------------------------------------------------
  609. //
  610. //    Scrolls the display down one record.
  611. //
  612. // Parameters
  613. //
  614. //    None.
  615. //
  616. // Return Value
  617. //
  618. //    None.
  619. //
  620. // Description
  621. //
  622. //      1.  Make sure you are not at the first record in the database.
  623. //
  624. //    2.  Decrement the top record pointer.
  625. //
  626. //    3.  Go to the top record and get the data.
  627. //
  628. //    4.  For all the fields, delete the last string in the list and insert
  629. //    the new data at the first string position in the list.
  630. //
  631. // End ---------------------------------------------------------------------
  632.  
  633. // member PXError of DBDISPLAY //
  634.  
  635. inline void DBDISPLAY::PXError(int org)
  636. {
  637.     // Call base class error handler.
  638.  
  639.     PXEngObject::PXError(org);
  640.  
  641.     // Send the PX Engine error message back to the parent window
  642.  
  643.     if(EngDataPtr->Errors.pxerr != PXSUCCESS)
  644.     {
  645.         // Because you may have the display update flag reset so
  646.         // that no updates can occur while the list boxes are being
  647.         // updated, you should make sure it's set before you dispatch
  648.         // the message or Windows will eventually crash because of
  649.         // the inability to process message traffic!!!!
  650.  
  651.         UpdateFlag = 1;
  652.  
  653.         SendMessage(AP->Parent->HWindow,WM_PXERROR,0,0);
  654.     }
  655. }
  656.  
  657. // Summary -----------------------------------------------------------------
  658. //
  659. //    If you get an error, send a message back to the parent window.  This
  660. //    will dispatch all PDOX errors back to the parent window.
  661. //
  662. // End ---------------------------------------------------------------------
  663.  
  664. #endif // DBDISPLY_CPP //